/*
 * ResultManager.cpp
 *
 *  Created on: 14/10/2011
 *      Author: mario
 */

#include "ResultManager.h"
#include "../../util/NodoConteo.h"
#include "../../util/Utils.h"
#include "../encryption/VigenereEncryptor.h"

ResultManager::ResultManager() {

}

ResultManager::~ResultManager() {
}

//TODO not
Conteo *ResultManager::getConteoPorId(int id)
{
	tree::BPlusTree * tree= new tree::BPlusTree(CONTEOS,BLOCKSIZE);

	tree::Record  * record= new tree::Record();
	record->setKey(id);
	tree::Record  * conteoRec = tree->find(record);
	if(conteoRec != NULL) {
		stringstream sss(ios_base::in| ios_base::out| ios_base::binary);
		sss.write(conteoRec->getData(), conteoRec->getDataSize());
		return Conteo::toObject(&sss);
	}
	return NULL;
}

//TODO not
Conteo *ResultManager::getConteoPorLista(Lista *lista)
{
	tree::BPlusTree * tree= new tree::BPlusTree(CONTEOS,BLOCKSIZE);

	tree::Record  * record= new tree::Record();
	record->setKey(lista->getId());
	tree::Record  * conteoRec = tree->find(record);
	if(conteoRec != NULL) {
		stringstream sss(ios_base::in| ios_base::out| ios_base::binary);
		sss.write(conteoRec->getData(), conteoRec->getDataSize());
		return Conteo::toObject(&sss);
	}
	return NULL;
}



List *ResultManager::retriveConteos(int lista, int eleccion, int distrito)
{
	List* ret = new List();

	tree::BPlusTree* tree = new tree::BPlusTree(CONTEOS, BLOCKSIZE);
	tree::Record* record = tree->iterate();

	if(lista > 0 || eleccion > 0 || distrito > 0) {
		while(record != NULL){
			stringstream ss(ios_base::in| ios_base::out| ios_base::binary);
			ss.write(record->getData(), record->getDataSize());
			Conteo* conteo = Conteo::toObject(&ss);
			bool valid = true;
			if(lista > 0 && lista != conteo->getLista()->getId()){
				valid = false;
			}
			if(eleccion > 0 && eleccion != conteo->getEleccion()->getId()){
				valid = false;
			}
			if(distrito > 0 && distrito != conteo->getDistrito()->getId()){
				valid = false;
			}
			if(valid){
				NodoConteo* nodo = new NodoConteo();
				nodo->setNodeValue(conteo);
				ret->add(nodo);
			}
			record = tree->iterate();
		}
	}

	return ret;
}

int ResultManager::saveConteo(Conteo *conteo, bool save)
{
	int result;
	tree::BPlusTree * tree = new tree::BPlusTree(CONTEOS, BLOCKSIZE);

	stringstream ss(ios_base::in | ios_base::out | ios_base::binary);
	conteo->toData(&ss);
	tree::Record* record = new tree::Record();
	record->edit(conteo->getId(), &ss);

	if (!save){
		result = tree->modify(record);
	}else {
		result = tree->insert(record);
	}

	return result;
}

int getConteoFullId(int lista, int eleccions, int distrito){
	string l = Utils::intToString(lista);
	string e = Utils::intToString(eleccions);
	string d = Utils::intToString(distrito);

	string newId = l + e +d;
	return Utils::stringToInt(newId);
}

int ResultManager::getReportValue(int distrito, int eleccion, int lista)
{
	int fullId = getConteoFullId(lista, eleccion, distrito);
	Conteo* conteo = ResultManager::getConteoPorId(fullId);
	if(conteo != NULL){
		return conteo->getCantidad();
	}
	List* conteos = ResultManager::retriveConteos(lista, eleccion, distrito);
	int total = 0;
	if(conteos != NULL){
		for(int i = 0; i < conteos->getSize(); i++){
			NodoConteo* nodo = (NodoConteo*) conteos->get(i);
			Conteo* c = nodo->getNodeValue();
			total += c->getCantidad();
		}
	}
	return total;
}


void ResultManager::writeReportFile(stringstream *ss) {

	ofstream file;
	file.open("resources/reporte");

	VigenereEncryptor* vig = new VigenereEncryptor();

	string enciphered = vig->encipher(ss->str());

	//cout << ss->str() << endl;
	//cout << enciphered << endl;

	file << enciphered;
	file.close();

}

string ResultManager::readReportFile() {

	ifstream file;
	file.open("resources/reporte");
	stringstream ss(ios_base::in| ios_base::out| ios_base::binary);
	string line;
	VigenereEncryptor* vig = new VigenereEncryptor();

	ss << file.rdbuf();
	file.close();
	//cout << ss.str() << endl;
	return vig->decipher(ss.str());
}

string ResultManager::readEncryptedReportFile() {

	ifstream file;
	file.open("resources/reporte");
	stringstream ss(ios_base::in| ios_base::out| ios_base::binary);
	string line;
	VigenereEncryptor* vig = new VigenereEncryptor();

	ss << file.rdbuf();
	file.close();
	return ss.str();
}

void ResultManager::kasiskiAttack() {

	KasiskiAttack * kas= new KasiskiAttack();
	kas->attack("resources/reporte");

}
